package com.fjl.array.leetcode1658;

/**
 * @Description
 * @Author: 01195
 * @Date: 2025/3/19 15:42
 */
/*
给你一个整数数组 nums 和一个整数 x 。每一次操作时，你应当移除数组 nums 最左边或最右边的元素，然后从 x 中减去该元素的值。请注意，需要 修改 数组以供接下来的操作使用。
如果可以将 x 恰好 减到 0 ，返回 最小操作数 ；否则，返回 -1 。
示例 1：
    输入：nums = [1,1,4,2,3], x = 5
    输出：2
    解释：最佳解决方案是移除后两个元素，将 x 减到 0 。
示例 2：
    输入：nums = [5,6,7,8,9], x = 4
    输出：-1
示例 3：
    输入：nums = [3,2,20,1,1,3], x = 10
    输出：5
    解释：最佳解决方案是移除后三个元素和前两个元素（总共 5 次操作），将 x 减到 0 。
这道题等价于让你寻找 nums 中元素和为 sum(nums) - x 的最长子数组。
使用滑动窗口算法需要搞清楚以下几个问题：
1、什么时候应该扩大窗口？
2、什么时候应该缩小窗口？
3、什么时候得到一个合法的答案？
针对本题，以上三个问题的答案是：
1、当窗口内元素之和小于目标和 target 时，扩大窗口，让窗口内元素和增加。
2、当窗口内元素之和大于目标和 target 时，缩小窗口，让窗口内元素和减小。
3、当窗口内元素之和等于目标和 target 时，找到一个符合条件的子数组，我们想找的是最长的子数组长度。
 */
public class Clazz {
    public int minOperations(int[] nums, int x) {
        // 计算nums总和
        int sums = 0;
        for (int i = 0; i < nums.length; i++) {
            sums += nums[i];
        }
        // 目标值
        int target = sums - x;
        // 记录窗口数字之和
        int window = 0;
        int left = 0, right = 0;
        // 记录目标子数组的最大长度
        int maxLen = Integer.MIN_VALUE;
        while (right < nums.length) {
            window += nums[right];
            right++;
            while (window > target && left < right) {
                window -= nums[left];
                left++;
            }
            if (window == target) {
                maxLen = Math.max(maxLen, right - left);
            }
        }
        // 目标子数组的最大长度可以推导出需要删除的字符数量
        return maxLen == Integer.MIN_VALUE ? -1 : nums.length - maxLen;
    }

    public static void main(String[] args) {
        System.out.println(new Clazz().minOperations(new int[]{1,1}, 3));
    }
}
